//TODO:  Map::new().insert().insert().insert();


use std::fmt::{self, Display};

use crate::value::Value;
use crate::bytes::Bytes;
use crate::curly_bracket_map_flag::CurlyBracketMapFlag;

use std::collections::HashMap;
use serde::ser::{self, SerializeMap};
use serde::de::{self,MapAccess};

#[derive(Debug, Default)]
pub struct Map(HashMap<String, Value>);

impl Map {
    #[inline]
    pub fn new() -> Self {
        Self (HashMap::new())
    }
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Self (HashMap::with_capacity(capacity))
    }
    #[inline]
    pub fn len(&self) -> usize {
        self.0.len()
    }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    
    #[inline]
    pub fn insert(&mut self, key: String, value: Value) {
        if !value.is_empty() {
            self.0.insert(key, value);
        }
    }
    #[inline]
    fn insert_kstr(&mut self, key: &str, value: Value) {
        self.insert(key.to_string(),  value);
    }

    #[inline]
    pub fn insert_kstr_vstr(&mut self, key: &str, value: &str) 
    {
        self.insert_kstr(key, Value::String(value.to_string()));
    }

    #[inline]
    pub fn insert_kstr_vfloat32(&mut self, key: &str, value: f32)
    {
        self.insert_kstr_vfloat(key, value.into());
    }
    #[inline]
    pub fn insert_kstr_vfloat64(&mut self, key: &str, value: f64)
    {
        self.insert_kstr_vfloat(key, value);
    }

    #[inline]
    fn insert_kstr_vfloat(&mut self, key: &str, value: f64)
    {
        self.insert_kstr(key, Value::Float(value));
    }


    #[inline]
    pub fn insert_kstr_vi8(&mut self, key: &str, value: i8){
        self.insert_kstr_vnumber(key, value.into());
    }
    #[inline]
    pub fn insert_kstr_vi16(&mut self, key: &str, value: i16){
        self.insert_kstr_vnumber(key, value.into());
    }
    #[inline]
    pub fn insert_kstr_vi32(&mut self, key: &str, value: i32){
        self.insert_kstr_vnumber(key, value.into());
    }
    #[inline]
    pub fn insert_kstr_vi64(&mut self, key: &str, value: i64){
        self.insert_kstr_vnumber(key, value);
    }

    #[inline]
    fn insert_kstr_vnumber(&mut self, key: &str, value: i64)
    {
        self.insert_kstr(key, Value::Number(value));
    }
    #[inline]
    pub fn insert_kstr_vbool(&mut self, key: &str, value: bool) 
    {
        self.insert_kstr(key, Value::Bool(value));
    }

    #[inline]
    pub fn insert_array(&mut self, key: String, arr: Vec<Value>) {
        if !arr.is_empty(){
            let new_arr: Vec<Value> = arr.into_iter().filter(|v| !v.is_empty()).collect();

            if !new_arr.is_empty() {
                self.0.insert(key, Value::Array(new_arr));
            }
        }
    }
    #[inline]
    pub fn insert_kstr_array(&mut self, key: &str, arr: Vec<Value>) {
        self.insert_array(key.to_string(), arr);
    }

    #[inline]
    pub fn insert_kstr_vbytes(&mut self, key: &str, bytes: &[u8]) {
        self.insert_bytes(key.to_string(), bytes);
    }
    #[inline]
    pub fn insert_bytes(&mut self, key: String, bytes: &[u8]) {
        if !bytes.is_empty(){
            self.0.insert(key, Value::Bytes(Bytes::new(bytes)));
        }
    }

    #[inline]
    pub fn insert_object(&mut self, key: String, map: Map) {
        if !map.is_empty() {
            let new_map: Map = map.into_iter().filter(|(_, y)|!y.is_empty()).collect();

            if !new_map.is_empty() {
                self.0.insert(key, Value::Object(new_map));
            }
        }
    }
    #[inline]
    pub fn insert_kstr_object(&mut self, key: &str, map: Map) {
        self.insert_object(key.to_string(), map);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.0.clear()
    }
    #[inline]
    pub fn contains_key(&self, k: &str) -> bool 
    {
        self.0.contains_key(k)
    }
    #[inline]
    pub fn remove(&mut self, k: &str) -> Option<Value> {
        self.0.remove(k)
    }
    #[inline]
    pub fn remove_entry(&mut self, k: &str) -> Option<(String, Value)> {
        self.0.remove_entry(k)
    }
    #[inline]
    pub fn get(&self, k: &str) -> Option<&Value> {
        self.0.get(k)
    }
    #[inline]
    pub fn get_mut(&mut self, k: &str) -> Option<&mut Value> {
        self.0.get_mut(k)
    }
    #[inline]
    pub fn get_key_value(&self, k: &str) -> Option<(&String, &Value)> {
        self.0.get_key_value(k)
    }
    #[inline]
    pub fn retain<F>(&mut self, f: F) 
    where 
        F: FnMut(&String, &mut Value) -> bool,
    {
        self.0.retain(f)
    }

    //TODO: entry -> Entry
    //TODO: keys() -> Keys
    //TODO: values() -> Values
    //TODO: values_mut() -> ValuesMut
    
    
    #[inline]
    pub fn iter(&self) -> Iter<'_> {
        Iter {
            iter: self.0.iter()
        }
    }
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<'_> {
        IterMut {
            iter: self.0.iter_mut()
        }
    }
}




pub struct Iter<'a> {
    iter: std::collections::hash_map::Iter<'a, String, Value>,
}
impl<'a> Iterator for Iter<'a> {

    type Item = (&'a String, &'a Value);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>){
        self.iter.size_hint()
    }
}
/*
impl<'a> DoubleEndedIterator for Iter<'a> { //TODO: what is the usage ?
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}*/
impl<'a> ExactSizeIterator for Iter<'a> { //TODO: what is the usage ?
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}
impl<'a> std::iter::FusedIterator for Iter<'a> {} //TODO: what is the usage ?


pub struct IterMut<'a> {
    iter: std::collections::hash_map::IterMut<'a, String, Value>,
}

impl<'a>  Iterator for IterMut<'a> {
    type Item =( &'a String, &'a mut Value);
    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>){
        self.iter.size_hint()
    }
}
impl<'a> ExactSizeIterator for IterMut<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.iter.len()
    }
}
impl<'a> std::iter::FusedIterator for IterMut<'a> {}




impl ser::Serialize for Map {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 
    where 
        S: ser::Serializer
    {
        let n = CurlyBracketMapFlag::remove_curly_bracket(self.len());
        let mut state = serializer.serialize_map(n)?;
        self.iter()
            .filter(|(_, y)| !y.is_empty())
            .try_for_each(|(x, y)| state.serialize_entry(x, y))?;
        state.end()
    }
}

impl Display for Map {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = crate::to_string(self).map_err(|_| fmt::Error)?;
        write!(f, "{}", s)
    }
}

impl Clone  for Map {
    #[inline]
    fn clone(&self) -> Self {
        Self (self.0.clone())
    }
    #[inline]
    fn clone_from(&mut self, source: &Self) {
        self.0.clone_from(&source.0)
    }
}


pub struct IntoIter {
    iter: std::collections::hash_map::IntoIter<String, Value>
}

impl IntoIterator for Map {
    type Item  = (String, Value);
    type IntoIter = IntoIter; 
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            iter: self.0.into_iter()
        }
    }
}

impl Iterator for IntoIter {
    type Item = (String, Value);
    #[inline] 
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

impl FromIterator<(String, Value)> for Map { //What 's the usage 
    fn from_iter<T>(iter: T) -> Self 
    where 
        T: IntoIterator<Item=(String, Value)> , 
    {
        Map (FromIterator::from_iter(iter))
    }
}
impl Extend<(String, Value)> for Map { //What 's the usage
    fn extend<T>(&mut self, iter: T) 
    where 
        T: IntoIterator<Item = (String, Value)>,
    {
        self.0.extend(iter)
    }
}


impl PartialEq for Map {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}
impl Eq for Map {}



impl<'de> de::Deserialize<'de> for Map {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 
    where 
        D: de::Deserializer<'de>
    {
        struct MapVisitor;
        impl<'de> de::Visitor<'de> for MapVisitor {
            type Value = Map;
            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.write_str("expecting type of gtp::Map")
            }

            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> 
            where 
                A: MapAccess<'de> ,
            {
                let mut result = Map::new();
                while let Some((k, v)) = MapAccess::next_entry::<String, crate::value::Value>(&mut map)? {
                    result.insert(k, v);
                }
                Ok(result)
            }
        }
        deserializer.deserialize_struct("Map", &[], MapVisitor)
    }
}

//
//TODO: impl<'a, Q> ops::Index<&'a Q> for Map<String, Value> {}
//TODO: impl<'a, Q> ops::IndexMut<&'a Q> for Map<String, Value>





#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn map(){
        {
            let mut m = Map::default();
            assert!(m.is_empty());
            assert!(!m.contains_key("hello"));
            m.insert_kstr_vstr("hello", "world");
            assert!(m.contains_key("hello"));

            m.insert_kstr_vi64("hello1", 123_i64);
            assert_eq!(2, m.len());
            m.remove("hello1").unwrap();
            assert_eq!(1, m.len());

            m.clear();
            assert!(m.is_empty());
        }

        {
            let mut m = Map::with_capacity(16);
            m.insert_kstr_vstr("hello", "word");
            m.insert_kstr_vbool("hello1", true);
            assert_eq!(2, m.len());
            println!("serializer map: {}", crate::to_string(&m).unwrap()); 


            let mut m2 = Map::with_capacity(8);
            m2.insert_kstr_vi64("sub_hello", 123_i64);
            m2.insert_kstr_vbool("bool", true);
            m2.insert_kstr_vfloat("sub_hello1", 3.456);
            m.insert_kstr_object("sub_map2", m2);

            let empty_map = Map::with_capacity(2);
            m.insert_kstr_object("empty_map", empty_map);

            let arr = vec![Value::Number(1), Value::Float(2.0), Value::Bool(false), Value::String("array_string".to_string())];
            m.insert_kstr_array("sub_array", arr);

            m.insert_kstr_array("empty_array", vec![]);

            println!("serializer map: {}", crate::to_string(&m).unwrap()); 
        }
    }
    #[test]
    fn empty_map_when_insert() {
        { // array { empty_array: [ "", [], {} ] 
            let v = vec![Value::String("".to_string()), Value::Array(vec![]), Value::Object(Map::with_capacity(1))];
            let mut m = Map::new();
            m.insert_kstr_array("empty_array", v);
            assert!(m.is_empty());
        }

        { // string
            let mut m = Map::with_capacity(4);
            m.insert_kstr_vstr("hello", "");
            assert!(m.is_empty());
        }

        { // map = {sub_map={hello=world,empty_string=[],empty_string=""}}
            let expect = "sub_map={hello=world}";
            let mut m = Map::new();
            {
                let mut sub_map = Map::new();
                sub_map.insert_kstr_vstr("hello", "world");
                sub_map.insert_kstr_vstr("empty_string", "");
                sub_map.insert_kstr_array("empty_array", vec![]);
                m.insert_kstr_object("sub_map", sub_map);
            }
            assert_eq!(expect, format!("{m}"));
        }
    }

    #[test]
    // IntoInterator =>  self.into_iter()-> Iterator<Item=A> (Not &A, &mut A)
    // Extend::extend(iter: IntoIterator<Item = A>); 
    // Collect -> FromIterator<A> -> <T> T is deduced Type
    fn into_iterator(){
        { //Extend 
            let mut message = String::from("Hello");
            let v = vec!['a', 'b', 'c'];
            message.extend(v.clone()); //extend -> use IntoIterator
            assert_eq!("Helloabc", message);
            assert_eq!(vec!['a', 'b', 'c'], v);
        }
        {   //collect -> FromIterator<char> -> Self;  
            let v: Vec<char> = vec!['a', 'b', 'c'];
            let n_v: Vec<char> = v.into_iter().collect();//impl FromIterator for Vec<char>, deduce from return <T>
            assert_eq!(vec!['a', 'b', 'c'], n_v);
            //assert_eq!(vec!['a', 'b', 'c'], v); //compile error: v is moved (v.into_iter())
        }
    }

    #[test]
    fn cmp(){
        {
            let mut map = Map::with_capacity(6);
            let mut map_other = Map::with_capacity(4);
            assert_eq!(map, map_other);

            map.insert_kstr_vstr("hello","world");
            map_other.insert_kstr_vstr("hello","world");
            assert_eq!(map, map_other);
        }
    }

    
    //TODO: #[test] Keys, Values, ValuesMut
    //TODO: #[test] Entry
    #[test]
    fn map_deserialize(){
        let src = "hello=world,world=hello";
        let map = crate::from_str::<Map>(src).unwrap();
        assert_eq!(map.len() , 2);

        let v = map.get("hello").unwrap();
        assert!(v.is_bytes());
        assert_eq!(Bytes::new(&b"world"[..]), *v.as_bytes().unwrap());

        let src = "hello={key1=v1,k2=v2}";
        let map = crate::from_str::<Map>(src).unwrap();
        assert_eq!(map.len() , 1);
        let hello = map.get("hello").unwrap();
        assert!(hello.is_object());

        let object_hello = hello.as_object().unwrap();
        assert_eq!(object_hello.len(), 2);

        object_hello.iter()
            .for_each( |(k, v)| {
                println!("{k}:{v}");
            });

        let src = "hello=[string1,string2]";
        let map = crate::from_str::<Map>(src).unwrap();
        assert_eq!(map.len() , 1);
        let hello = map.get("hello").unwrap();
        assert!(hello.is_array());
        let object_hello = hello.as_array().unwrap();
        assert_eq!(object_hello.len(), 2);

        let src = "hello=[string1,string2],world={k1=v1},haha=ahah";
        let map = crate::from_str::<Map>(src).unwrap();
        assert_eq!(map.len() , 3);

        let node = map.get("hello").unwrap();
        assert!(node.is_array());

        let node = map.get("world").unwrap();
        assert!(node.is_object());

        let node = map.get("haha").unwrap();
        assert!(node.is_bytes());
    }
}
